package com.opensource.lzx.restartclient.netty.handler;

import com.opensource.lzx.proto.OperationType;
import com.opensource.lzx.proto.RequestContext;
import com.opensource.lzx.proto.ServiceRequest;
import com.opensource.lzx.restartclient.netty.NettyClientTemplate;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author: 739891618@qq.com
 * @Date: 2022-11-13 11:19:35
 * @ClassName: HeartBeatHandler
 * @Describe: this is a ...
 */
@Slf4j
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("Netty server connect success and send to heart beat request.");
        RequestContext context = buildRequest();

        // 因为设置了每5秒就需要检测一下服务健康问题,所以该处需要定时发送心跳检测
        ctx.executor().scheduleAtFixedRate(
                () -> ctx.channel().writeAndFlush(buildRequest()), 4, 4, TimeUnit.SECONDS);
        // 注册服务到本地
        NettyClientTemplate.registerChannel(ctx.channel());

        ctx.channel().writeAndFlush(context);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RequestContext context = (RequestContext) msg;
        if (context.getResponse().getType().getNumber() == OperationType.HEARTBEAT_RESPONSE.getNumber()) {
            log.info("Receive server response heart beat info: {}", context.getResponse().getRequestId());
        } else {
            super.channelRead(ctx, msg);
        }
    }

    private RequestContext buildRequest() {
        ServiceRequest.Builder serviceBuilder = ServiceRequest.newBuilder();
        serviceBuilder.setType(OperationType.HEARTBEAT_REQUEST);
        serviceBuilder.setRequestId(UUID.randomUUID().toString().replaceAll("-", ""));

        RequestContext.Builder context = RequestContext.newBuilder();
        context.setRequest(serviceBuilder.build());
        return context.build();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("HeartBeat handler error and message: ", cause);
        ctx.channel().close();
    }
}
